梦想不会自己发光,真正闪耀的是那个为梦狂奔的你。献给知行的孩子们!(Eric.He著)
本教程将从 C++ STL 标准库的核心概念、六大组件、各类容器到常用算法,全面拆解 STL 的核心用法,帮助你掌握这一提升 C++ 编程效率的核心工具。
STL(Standard Template Library,标准模板库)是 C++ 标准库的核心组成部分,是一套通用的模板化数据结构和算法库。它将数据结构与算法分离,通过模板实现代码复用,大幅提升 C++ 编程效率和代码可维护性。
STL 的核心设计理念是:数据结构和算法的分离与泛化,即算法不依赖具体的数据结构,数据结构也不依赖具体的算法,通过迭代器(Iterator)作为两者的桥梁。
| 组件名称 | 核心作用 | 典型示例 |
|---|---|---|
| 容器(Container) | 存储数据的模板化数据结构 | vector、list、set、map、queue、stack |
| 算法(Algorithm) | 操作容器中数据的通用算法 | sort、find、reverse、unique、max_element |
| 迭代器(Iterator) | 连接容器与算法的"桥梁",遍历容器元素 | iterator、const_iterator、reverse_iterator |
| 仿函数(Functor) | 重载()运算符的类/结构体,替代函数指针 | less<>、greater<>、自定义比较仿函数 |
| 适配器(Adapter) | 封装已有组件,改变其接口或行为 | queue(基于deque)、stack(基于deque) |
| 分配器(Allocator) | 管理容器内存的分配与释放 | std::allocator(默认分配器) |
序列式容器(Sequence Container)按插入顺序存储元素,元素可通过索引访问,核心特点是元素有序且可重复。
vector 是基于动态数组实现的序列式容器,支持随机访问,尾部插入/删除效率高,中间插入/删除效率低(需移动元素)。
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 1. 创建vector容器
vector<int> vec; // 空vector
vector<int> vec2(5, 10); // 5个元素,每个元素值为10
vector<int> vec3 = {1, 2, 3, 4, 5}; // 初始化列表
// 2. 插入元素
vec.push_back(1); // 尾部插入
vec.push_back(2);
vec.insert(vec.begin() + 1, 3); // 在索引1位置插入3
// 3. 访问元素
cout << "vec[0] = " << vec[0] << endl; // 直接访问(无越界检查)
cout << "vec.at(1) = " << vec.at(1) << endl; // 安全访问(有越界检查)
cout << "第一个元素:" << vec.front() << endl;
cout << "最后一个元素:" << vec.back() << endl;
// 4. 遍历元素
cout << "\n遍历vec:";
for (int i = 0; i < vec.size(); i++) {
cout << vec[i] << " ";
}
cout << endl;
// 迭代器遍历
cout << "迭代器遍历:";
for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++) {
cout << *it << " ";
}
cout << endl;
// 5. 删除元素
vec.pop_back(); // 删除尾部元素
vec.erase(vec.begin() + 1); // 删除索引1位置的元素
// 6. 其他常用操作
cout << "\nvec大小:" << vec.size() << endl;
cout << "vec容量:" << vec.capacity() << endl;
vec.resize(5); // 调整大小为5
vec.clear(); // 清空所有元素
cout << "清空后大小:" << vec.size() << endl;
return 0;
}
deque(Double-Ended Queue)是双向队列,支持头部/尾部高效插入/删除,也支持随机访问,内存由多个连续块组成。
#include <iostream>
#include <deque>
using namespace std;
int main() {
deque dq;
// 1. 插入元素
dq.push_back(10); // 尾部插入
dq.push_back(20);
dq.push_front(5); // 头部插入
dq.push_front(1);
// 2. 访问元素
cout << "dq[1] = " << dq[1] << endl;
cout << "头部元素:" << dq.front() << endl;
cout << "尾部元素:" << dq.back() << endl;
// 3. 遍历
cout << "\n遍历deque:";
for (deque<int>::iterator it = dq.begin(); it != dq.end(); it++) {
cout << *it << " ";
}
cout << endl;
// 4. 删除元素
dq.pop_front(); // 删除头部
dq.pop_back(); // 删除尾部
cout << "删除后遍历:";
for (int num : dq) { // 范围for遍历
cout << num << " ";
}
cout << endl;
return 0;
}
list 是双向链表实现的序列式容器,不支持随机访问,但任意位置插入/删除效率高(O(1))。
#include <iostream>
#include <list>
using namespace std;
int main() {
list lst = {3, 1, 4, 2, 5};
// 1. 插入元素
lst.push_back(6);
lst.push_front(0);
lst.insert(++lst.begin(), 10); // 在第二个位置插入10
// 2. 遍历
cout << "遍历list:";
for (int num : lst) {
cout << num << " ";
}
cout << endl;
// 3. 排序、反转
lst.sort(); // 升序排序
cout << "排序后:";
for (int num : lst) {
cout << num << " ";
}
cout << endl;
lst.reverse(); // 反转
cout << "反转后:";
for (int num : lst) {
cout << num << " ";
}
cout << endl;
// 4. 删除元素
lst.pop_front();
lst.pop_back();
lst.remove(2); // 删除所有值为2的元素
cout << "删除后:";
for (int num : lst) {
cout << num << " ";
}
cout << endl;
return 0;
}
关联式容器(Associative Container)基于键(Key)存储元素,元素自动排序,不支持随机访问,核心特点是查找效率高(O(logn))。
set 是有序不重复的集合,基于红黑树实现,键与值相同,自动按升序排序。
#include <iostream>
#include <set>
using namespace std;
int main() {
// 1. 创建set(默认升序)
set<int> s;
// 降序set
set<int, greater<int>> s2;
// 2. 插入元素
s.insert(5);
s.insert(2);
s.insert(8);
s.insert(2); // 重复元素,插入失败
s2.insert(5);
s2.insert(2);
s2.insert(8);
// 3. 遍历
cout << "升序set:";
for (int num : s) {
cout << num << " ";
}
cout << endl;
cout << "降序set:";
for (int num : s2) {
cout << num << " ";
}
cout << endl;
// 4. 查找元素
auto it = s.find(5);
if (it != s.end()) {
cout << "\n找到元素:" << *it << endl;
}
// 统计元素个数(set中只能是0或1)
cout << "元素2的个数:" << s.count(2) << endl;
// 5. 删除元素
s.erase(2); // 删除值为2的元素
s.erase(s.begin()); // 删除第一个元素
cout << "删除后set:";
for (int num : s) {
cout << num << " ";
}
cout << endl;
return 0;
}
map 是键值对(key-value)的有序集合,基于红黑树实现,键唯一,自动按键升序排序。
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
// 1. 创建map(键:字符串,值:整数)
map<string, int> mp;
// 2. 插入键值对
mp["张三"] = 90;
mp["李四"] = 85;
mp["王五"] = 95;
mp.insert(pair<string, int>("赵六", 88)); // 插入方式2
mp.insert({"孙七", 92}); // 插入方式3
// 3. 访问值
cout << "张三的成绩:" << mp["张三"] << endl;
// 访问不存在的键,会自动插入该键,值为默认值(0)
cout << "周八的成绩:" << mp["周八"] << endl;
// 4. 遍历
cout << "\n遍历map:" << endl;
for (auto& pair : mp) {
cout << pair.first << ":" << pair.second << endl;
}
// 迭代器遍历
cout << "\n迭代器遍历:" << endl;
for (map<string, int>::iterator it = mp.begin(); it != mp.end(); it++) {
cout << it->first << ":" << it->second << endl;
}
// 5. 查找键
auto it = mp.find("李四");
if (it != mp.end()) {
cout << "\n找到李四:" << it->second << endl;
}
// 6. 删除键值对
mp.erase("周八"); // 删除键为"周八"的元素
mp.erase(mp.begin()); // 删除第一个元素
cout << "\n删除后map:" << endl;
for (auto& pair : mp) {
cout << pair.first << ":" << pair.second << endl;
}
return 0;
}
容器适配器(Container Adapter)是对已有容器的封装,隐藏底层容器的接口,提供特定的操作接口,核心包括queue(队列)和stack(栈)。
queue 是先进先出(FIFO)的队列,默认基于deque实现,仅支持头部删除、尾部插入。
#include <iostream>
#include <queue>
using namespace std;
int main() {
queue<int> q;
// 1. 入队
q.push(10);
q.push(20);
q.push(30);
// 2. 访问元素
cout << "队头元素:" << q.front() << endl;
cout << "队尾元素:" << q.back() << endl;
cout << "队列大小:" << q.size() << endl;
// 3. 出队
q.pop(); // 删除队头
cout << "\n出队后队头:" << q.front() << endl;
cout << "队列是否为空:" << (q.empty() ? "是" : "否") << endl;
// 遍历(需逐个出队)
cout << "\n遍历队列:";
while (!q.empty()) {
cout << q.front() << " ";
q.pop();
}
cout << endl;
return 0;
}
stack 是后进先出(LIFO)的栈,默认基于deque实现,仅支持顶部插入、顶部删除。
#include <iostream>
#include <stack>
using namespace std;
int main() {
stack st;
// 1. 入栈
st.push(1);
st.push(2);
st.push(3);
// 2. 访问元素
cout << "栈顶元素:" << st.top() << endl;
cout << "栈大小:" << st.size() << endl;
// 3. 出栈
st.pop(); // 删除栈顶
cout << "\n出栈后栈顶:" << st.top() << endl;
cout << "栈是否为空:" << (st.empty() ? "是" : "否") << endl;
// 遍历(需逐个出栈)
cout << "\n遍历栈:";
while (!st.empty()) {
cout << st.top() << " ";
st.pop();
}
cout << endl;
return 0;
}
STL算法库(<algorithm>)提供了大量通用算法,适用于各类容器,算法通过迭代器操作容器元素,不依赖具体容器类型。
sort 是基于快速排序的优化排序算法,默认升序排序,支持自定义比较规则,时间复杂度O(nlogn)。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 自定义降序比较函数
bool cmp(int a, int b) {
return a > b;
}
int main() {
vector<int> vec = {5, 2, 9, 1, 5, 6};
// 1. 默认升序排序
sort(vec.begin(), vec.end());
cout << "升序排序:";
for (int num : vec) {
cout << num << " ";
}
cout << endl;
// 2. 降序排序(自定义比较函数)
sort(vec.begin(), vec.end(), cmp);
cout << "降序排序(函数):";
for (int num : vec) {
cout << num << " ";
}
cout << endl;
// 3. 降序排序(仿函数)
sort(vec.begin(), vec.end(), greater<int>());
cout << "降序排序(仿函数):";
for (int num : vec) {
cout << num << " ";
}
cout << endl;
return 0;
}
二分查找算法要求容器已排序,lower_bound 返回第一个≥目标值的迭代器,upper_bound 返回第一个>目标值的迭代器。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> vec = {1, 3, 5, 5, 7, 9};
// 1. lower_bound:第一个≥5的元素
auto it1 = lower_bound(vec.begin(), vec.end(), 5);
if (it1 != vec.end()) {
cout << "lower_bound(5):" << *it1 << " 索引:" << it1 - vec.begin() << endl;
}
// 2. upper_bound:第一个>5的元素
auto it2 = upper_bound(vec.begin(), vec.end(), 5);
if (it2 != vec.end()) {
cout << "upper_bound(5):" << *it2 << " 索引:" << it2 - vec.begin() << endl;
}
// 3. 查找不存在的元素
auto it3 = lower_bound(vec.begin(), vec.end(), 6);
if (it3 == vec.end()) {
cout << "未找到6,插入位置:" << it3 - vec.begin() << endl;
}
return 0;
}
next_permutation 生成当前序列的下一个字典序排列,prev_permutation 生成上一个字典序排列,返回bool值表示是否生成成功。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> vec = {1, 2, 3};
cout << "所有排列:" << endl;
do {
for (int num : vec) {
cout << num << " ";
}
cout << endl;
} while (next_permutation(vec.begin(), vec.end()));
// 重置为降序,生成上一个排列
vector<int> vec2 = {3, 2, 1};
cout << "\n上一个排列:" << endl;
if (prev_permutation(vec2.begin(), vec2.end())) {
for (int num : vec2) {
cout << num << " ";
}
}
cout << endl;
return 0;
}
reverse 反转容器中指定区间的元素顺序,时间复杂度O(n)。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> vec = {1, 2, 3, 4, 5};
cout << "反转前:";
for (int num : vec) {
cout << num << " ";
}
cout << endl;
// 反转整个容器
reverse(vec.begin(), vec.end());
cout << "反转后:";
for (int num : vec) {
cout << num << " ";
}
cout << endl;
// 反转部分区间(索引1-3)
reverse(vec.begin() + 1, vec.begin() + 4);
cout << "反转部分区间后:";
for (int num : vec) {
cout << num << " ";
}
cout << endl;
return 0;
}
unique 移除容器中连续的重复元素,返回去重后最后一个元素的迭代器,需配合erase删除冗余元素,使用前需排序(否则仅去重连续重复)。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> vec = {1, 2, 2, 3, 3, 3, 4};
cout << "去重前:";
for (int num : vec) {
cout << num << " ";
}
cout << endl;
// 去重(仅移除连续重复)
auto it = unique(vec.begin(), vec.end());
// 删除冗余元素
vec.erase(it, vec.end());
cout << "去重后:";
for (int num : vec) {
cout << num << " ";
}
cout << endl;
// 非连续重复需先排序
vector<int> vec2 = {2, 1, 2, 3, 1, 3};
sort(vec2.begin(), vec2.end());
vec2.erase(unique(vec2.begin(), vec2.end()), vec2.end());
cout << "排序后去重:";
for (int num : vec2) {
cout << num << " ";
}
cout << endl;
return 0;
}
min_element 返回容器中最小值的迭代器,max_element 返回最大值的迭代器,时间复杂度O(n)。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> vec = {5, 2, 9, 1, 7, 3};
// 最小值
auto min_it = min_element(vec.begin(), vec.end());
cout << "最小值:" << *min_it << " 索引:" << min_it - vec.begin() << endl;
// 最大值
auto max_it = max_element(vec.begin(), vec.end());
cout << "最大值:" << *max_it << " 索引:" << max_it - vec.begin() << endl;
return 0;
}
<algorithm>头文件,容器需包含对应头文件(如<vector>、<set>)。本教程从 STL 核心概念、六大组件到各类容器和常用算法,全面拆解了 STL 的核心用法。掌握 STL 是提升 C++ 编程效率和代码质量的关键,也是学习高级数据结构和算法的重要基础。